import glob
import subprocess
import os
import time
import zipfile
import re
# from androguard.core.bytecodes.dvm import DalvikVMFormat
from androguard.core.bytecode import TmpBlock
from androguard.core.analysis.analysis import Analysis
from androguard.misc import AnalyzeAPK
from asn1crypto import x509
import base64
# from androguard.core.bytecodes.apk import APK
from pathlib import Path
import binascii
from androguard.misc import AnalyzeAPK
import xml.etree.ElementTree as ET
import hashlib

def decompile_apk1(apk_path, output_dir):

    # 确保输出目录存在
    if not os.path.exists(output_dir):
        os.makedirs(output_dir)

    # 构建Apktool命令
    apktool_command = f"apktool d -f {apk_path} -o {output_dir}"

    try:
        # 使用subprocess.Popen执行命令，允许输入重定向以自动处理"Press any key to continue..."提示
        process = subprocess.Popen(apktool_command, shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)

        # 向stdin写入一个回车符来模拟按键，然后刷新缓冲区
        process.stdin.write('\n')
        process.stdin.flush()

        # 等待命令执行完成
        stdout, stderr = process.communicate()

        # 检查返回码，非0表示命令执行出错
        if process.returncode != 0:
            raise subprocess.CalledProcessError(process.returncode, apktool_command, output=stdout, stderr=stderr)

        print(f"APK文件已成功解压到{output_dir}")

    except subprocess.CalledProcessError as e:
        new_content=apk_path+'\n'
        with open('batch1反编译日志', 'a') as file:
            file.write(new_content)
        print(f"解压过程中发生错误: {e}")

import os
import subprocess

def decompile_apk2(apk_path, output_dir):
    # 确保输出目录存在
    if not os.path.exists(output_dir):
        os.makedirs(output_dir)

    # 构建Apktool命令
    apktool_command = f"apktool d -f {apk_path} -o {output_dir}"

    try:
        # 使用subprocess.Popen执行命令，指定编码处理输出和错误信息
        process = subprocess.Popen(apktool_command, shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True, encoding='utf-8', errors='replace')

        # 向stdin写入一个回车符来模拟按键，然后刷新缓冲区
        process.stdin.write('\n')
        process.stdin.flush()

        # 等待命令执行完成
        stdout, stderr = process.communicate()

        # 检查返回码，非0表示命令执行出错
        if process.returncode != 0:
            # 当错误发生时，将错误信息中的非法字符替换处理，避免直接打印时的编码错误
            stderr_processed = stderr.encode('utf-8', errors='replace').decode('utf-8')
            raise subprocess.CalledProcessError(process.returncode, apktool_command, output=stdout, stderr=stderr_processed)

        print(f"APK文件已成功解压到{output_dir}")

    except subprocess.CalledProcessError as e:
        new_content = apk_path + '\n'
        with open('batch1反编译日志', 'a', encoding='utf-8') as file:
            file.write(new_content)
        print(f"解压过程中发生错误: {e.stderr}")

# 示例调用
# decompile_apk1('path_to_your_apk.apk', 'output_directory')

#before apktool
class APKDataFilter:
    def __init__(self,path):
        self.path=path
        errorcount=0
        try:
            a, d, dx = AnalyzeAPK(self.path)
            self.a=a
            self.d=d
            self.dx=dx
        except Exception as e:
            print(self.path)
            errorcount=errorcount+1
            print(f"捕获到异常: {e}")

    def get_activities(self):
        activities=None
        try:
            activities=self.a.get_activities()
        except Exception as e:
            print(f"捕获到异常: {e}")
        return activities

    def get_package(self):
        package=None
        try:
            package=self.a.get_package()
        except Exception as e:
            print(f"捕获到异常: {e}")
        return None

    def get_app_name(self):
        app_name=None
        try:
            app_name=self.a.get_app_name()
        except Exception as e:
            print(f"捕获到异常: {e}")
        return app_name
    # 图标
    def get_app_icon(self):
        app_icon=None
        try:
            app_icon=self.a.get_app_icon()
        except Exception as e:
            print(f"捕获到异常: {e}")
        return app_icon
    # 版本字符串
    def get_androidversion_name(self):
        androidversion_name=None
        try:
            print(self.path)
            androidversion_name=self.a.get_androidversion_name()
        except KeyError:
            androidversion_name="未知版本名称"
        return androidversion_name
    # 数值版本
    def get_androidversion_code(self):
        androidversion_code=None
        try:
            androidversion_code=self.a.get_androidversion_code()
        except Exception as e:
            print(f"捕获到异常: {e}")
        return androidversion_code

    # 获取证书信息
    def get_certificates(self):
        print("APK is signed: {}".format(self.a.is_signed()))

        if self.a.is_signed():
            # Test if signed v1 or v2 or both
            print("APK is signed with: {}".format("both" if self.a.is_signed_v1() and
                                                            self.a.is_signed_v2() else "v1"
            if self.a.is_signed_v1() else "v2"))
        for cert in self.a.get_certificates():
            # 打印证书详情
            print("开发者（通常是颁发者）:", cert.issuer.human_friendly)
            print("MD-5 签名:", hashlib.md5(cert.contents).hexdigest())
            print("SHA-1 签名:", binascii.hexlify(cert.sha1).decode('utf-8'))
            print("SHA-256 签名:", binascii.hexlify(cert.sha256).decode('utf-8'))
            print("证书有效期:", cert.not_valid_before, "至", cert.not_valid_after)  # 证书有效期
            print("签名算法:", cert.signature_algo)
            print("哈希算法:", cert.hash_algo)
            print("序列号:", cert.serial_number)
            print("证书内容(DER 编码):", cert.contents.hex())  # 显示证书的DER编码内容

    def get_hash_algo(self):
        hash_algo=None
        try:
            for cert in self.a.get_certificates():
                return cert.hash_algo
        except Exception as e:
            print(f"捕获到异常: {e}")
        return hash_algo

    def get_serial_number(self):
        serial_number=None
        try:
            for cert in self.a.get_certificates():
                return cert.serial_number
        except Exception as e:
            print(f"捕获到异常: {e}")
        return serial_number

    def get_contents_der(self):
        contents_der=None
        try:
            for cert in self.a.get_certificates():
                return cert.contents.hex()
        except Exception as e:
            print(f"捕获到异常: {e}")
        return contents_der

    def get_issuer(self):
        issuer=None
        try:
            for cert in self.a.get_certificates():
                # 打印证书详情
                return cert.issuer.human_friendly
        except Exception as e:
            print(f"捕获到异常: {e}")
        return issuer


    def get_md5(self):
        md5=None
        try:
            for cert in self.a.get_certificates():
                return hashlib.md5(cert.contents).hexdigest()
        except Exception as e:
            print(f"捕获到异常: {e}")
        return md5

    def get_sha1(self):
        sha1=None
        try:
            for cert in self.a.get_certificates():
                return binascii.hexlify(cert.sha1).decode('utf-8')
        except Exception as e:
            print(f"捕获到异常: {e}")

        return sha1

    def get_sha256(self):
        sha256=None
        try:
            for cert in self.a.get_certificates():
                return binascii.hexlify(cert.sha256).decode('utf-8')
        except Exception as e:
            print(f"捕获到异常: {e}")

        return sha256

    def get_validity_period(self):
        validity_period=None
        try:
            for cert in self.a.get_certificates():
                return ' to '.join([cert.not_valid_before.strftime('%Y-%m-%d'),cert.not_valid_after.strftime('%Y-%m-%d')])
        except Exception as e:
            print(f"捕获到异常: {e}")
            validity_period=None
        return validity_period

    def get_signature_algo(self):
        signature_algo=None
        try:
            for cert in self.a.get_certificates():
                return cert.signature_algo
        except Exception as e:
            print(f"捕获到异常: {e}")

        return signature_algo

    def get_apk_signature_md5(self):
        try:
            certificates = self.a.get_certificates()
        except Exception as e:
            print(f"捕获到异常: {e}")
            return None
        if certificates:
            # 通常APK会有至少一个证书，这里我们只取第一个作为示例
            cert_der = certificates[0].get_der()
            # 计算DER编码的证书的MD5值
            import hashlib
            md5_hash = hashlib.md5(cert_der).hexdigest()
            return md5_hash
        else:
            print("未找到APK的签名证书。")
            return None
    # # 获取操作码
    # def get_DalvikOrder(self):
    #     dex_files = self.a.get_dex()
    #     byte_data = dex_files
    #     hex_data = binascii.hexlify(byte_data)
    #     dvm = DalvikVMFormat(binascii.unhexlify(hex_data))
    #     value=[]
    #     for current_class in dvm.get_classes():
    #         for method in current_class.get_methods():
    #             code = method.get_code()
    #         if code:
    #             bc = code.get_bc()
    #             for i in bc.get_instructions():
    #                 # print(f"操作码: {i.get_op_value()} 指令: {i.get_name()}")
    #                 value.append(i.get_op_value())
    #     return value
    # 获取意图
    # def get_intent(self):
    #     try:
    #         manifest_data = self.a.get_android_manifest_axml().get_xml()
    #     except Exception as e:
    #         print(f"捕获到异常: {e}")
    #         return None
    #     manifest_data = manifest_data.decode('utf-8')
    #     # print(manifest_data)
    #     pattern1 = r'<intent-filter>(.*?)</intent-filter>'
    #     matches = re.findall(pattern1, manifest_data, re.DOTALL)
    #     intent_filter_contents = []
    #     for match in matches:
    #         # intent_filter_contents.append(match.strip())
    #         lines=match.strip().split('\n')
    #         lines=[line.strip() for line in lines]
    #         intent_filter_contents.extend(lines)
    #     intent_filter_contents=[tmp for tmp in intent_filter_contents if not tmp.startswith("<data android:")]
    #     intent_filter_contents=[item.split('"')[1] for item in intent_filter_contents]
    #     return intent_filter_contents

    def get_intent(self):
        intent_filter_contents = []
        try:
            # 获取并解码manifest数据
            manifest_data = self.a.get_android_manifest_axml().get_xml()
            if manifest_data is not None:
                manifest_data = manifest_data.decode('utf-8')
            else:
                print("Manifest data is None.")
                return []
            # 使用正则表达式提取<intent-filter>内容
            pattern1 = r'<intent-filter>(.*?)</intent-filter>'
            matches = re.findall(pattern1, manifest_data, re.DOTALL)
            # 遍历匹配结果，清理并提取intent filter中的动作(action)
            for match in matches:
                lines = [line.strip() for line in match.strip().split('\n') if line.strip()]
                for line in lines:
                    # 直接寻找以android:name开头并提取双引号中的内容，跳过"data"标签
                    if line.startswith('<action android:name='):
                        action = line.split('android:name="')[1].split('"')[0]
                        intent_filter_contents.append(action)
        except Exception as e:
            print(f"捕获到异常: {e}")
            return []
        return intent_filter_contents

    def get_apk_size(self):
        file_size = os.path.getsize(self.path)
        return round(file_size / (1024 * 1024),2)

    def generate_ngrams(self,dalvik_value, n):
        dalvik_ngrams=[]
        for i in range(0, len(dalvik_value) - n + 1):
            dalvik_ngrams.append(dalvik_value[i:i+n])
        return dalvik_ngrams

# after apktool:
class ApkDecompiler:
    def __init__(self,apk_path,output_dir):
        self.apk_path=apk_path
        self.output_dir=output_dir
        errorcount=0
        try:
            a, d, dx = AnalyzeAPK(self.apk_path)
            self.a=a
            self.d=d
            self.dx=dx
        except Exception as e:
            print(self.apk_path)
            errorcount=errorcount+1
            print(f"捕获到异常: {e}")

    def get_activities(self):
        activities=[None]
        try:
            activities=self.a.get_activities()
        except Exception as e:
            print(f"捕获到异常: {e}")
        return activities

    def get_permissions(self):
        permissions=[None]
        try:
            permissions=self.a.get_permissions()
        except Exception as e:
            print(f"捕获到异常: {e}")
        return permissions
    def get_package(self):
        package=[None]
        try:
            package=self.a.get_package()
        except Exception as e:
            print(f"捕获到异常: {e}")
        return package

    def get_app_name(self):
        app_name=[None]
        try:
            app_name=self.a.get_app_name()
        except Exception as e:
            print(f"捕获到异常: {e}")
        return app_name
    # 图标
    def get_app_icon(self):
        app_icon=[None]
        try:
            app_icon=self.a.get_app_icon()
        except Exception as e:
            print(f"捕获到异常: {e}")
        return app_icon
    # 版本字符串
    def get_androidversion_name(self):
        try:
            print(self.apk_path)
            androidversion_name=self.a.get_androidversion_name()
        except KeyError:
            androidversion_name=None
        return androidversion_name
    # 数值版本
    def get_androidversion_code(self):
        androidversion_code=None
        try:
            androidversion_code=self.a.get_androidversion_code()
        except Exception as e:
            print(f"捕获到异常: {e}")
        return androidversion_code

    # 获取证书信息
    def get_certificates(self):
        print("APK is signed: {}".format(self.a.is_signed()))

        if self.a.is_signed():
            # Test if signed v1 or v2 or both
            print("APK is signed with: {}".format("both" if self.a.is_signed_v1() and
                                                            self.a.is_signed_v2() else "v1"
            if self.a.is_signed_v1() else "v2"))
        for cert in self.a.get_certificates():
            # 打印证书详情
            print("开发者（通常是颁发者）:", cert.issuer.human_friendly)
            print("MD-5 签名:", hashlib.md5(cert.contents).hexdigest())
            print("SHA-1 签名:", binascii.hexlify(cert.sha1).decode('utf-8'))
            print("SHA-256 签名:", binascii.hexlify(cert.sha256).decode('utf-8'))
            print("证书有效期:", cert.not_valid_before, "至", cert.not_valid_after)  # 证书有效期
            print("签名算法:", cert.signature_algo)
            print("哈希算法:", cert.hash_algo)
            print("序列号:", cert.serial_number)
            print("证书内容(DER 编码):", cert.contents.hex())  # 显示证书的DER编码内容

    def get_hash_algo(self):
        hash_algo=None
        try:
            for cert in self.a.get_certificates():
                return cert.hash_algo
        except Exception as e:
            print(f"捕获到异常: {e}")
        return hash_algo

    def get_serial_number(self):
        serial_number=None
        try:
            for cert in self.a.get_certificates():
                return cert.serial_number
        except Exception as e:
            print(f"捕获到异常: {e}")
        return serial_number

    def get_contents_der(self):
        contents_der=None
        try:
            for cert in self.a.get_certificates():
                return cert.contents.hex()
        except Exception as e:
            print(f"捕获到异常: {e}")
        return contents_der

    def get_issuer(self):
        issuer=None
        try:
            for cert in self.a.get_certificates():
                # 打印证书详情
                return cert.issuer.human_friendly
        except Exception as e:
            print(f"捕获到异常: {e}")
        return issuer


    def get_md5(self):
        md5=None
        try:
            for cert in self.a.get_certificates():
                return hashlib.md5(cert.contents).hexdigest()
        except Exception as e:
            print(f"捕获到异常: {e}")
        return md5

    def get_sha1(self):
        sha1=None
        try:
            for cert in self.a.get_certificates():
                return binascii.hexlify(cert.sha1).decode('utf-8')
        except Exception as e:
            print(f"捕获到异常: {e}")

        return sha1

    def get_sha256(self):
        sha256=None
        try:
            for cert in self.a.get_certificates():
                return binascii.hexlify(cert.sha256).decode('utf-8')
        except Exception as e:
            print(f"捕获到异常: {e}")

        return sha256

    def get_validity_period(self):
        validity_period=None
        try:
            for cert in self.a.get_certificates():
                return ' to '.join([cert.not_valid_before.strftime('%Y-%m-%d'),cert.not_valid_after.strftime('%Y-%m-%d')])
        except Exception as e:
            print(f"捕获到异常: {e}")
            validity_period=None
        return validity_period

    def get_signature_algo(self):
        signature_algo=None
        try:
            for cert in self.a.get_certificates():
                return cert.signature_algo
        except Exception as e:
            print(f"捕获到异常: {e}")

        return signature_algo

    def get_apk_signature_md5(self):
        try:
            certificates = self.a.get_certificates()
        except Exception as e:
            print(f"捕获到异常: {e}")
            return None
        if certificates:
            # 通常APK会有至少一个证书，这里我们只取第一个作为示例
            cert_der = certificates[0].get_der()
            # 计算DER编码的证书的MD5值
            import hashlib
            md5_hash = hashlib.md5(cert_der).hexdigest()
            return md5_hash
        else:
            print("未找到APK的签名证书。")
            return None
    # # 获取操作码
    # def get_DalvikOrder(self):
    #     dex_files = self.a.get_dex()
    #     byte_data = dex_files
    #     hex_data = binascii.hexlify(byte_data)
    #     dvm = DalvikVMFormat(binascii.unhexlify(hex_data))
    #     value=[]
    #     for current_class in dvm.get_classes():
    #         for method in current_class.get_methods():
    #             code = method.get_code()
    #         if code:
    #             bc = code.get_bc()
    #             for i in bc.get_instructions():
    #                 # print(f"操作码: {i.get_op_value()} 指令: {i.get_name()}")
    #                 value.append(i.get_op_value())
    #     return value
    # 获取意图
    # def get_intent(self):
    #     try:
    #         manifest_data = self.a.get_android_manifest_axml().get_xml()
    #     except Exception as e:
    #         print(f"捕获到异常: {e}")
    #         return None
    #     manifest_data = manifest_data.decode('utf-8')
    #     # print(manifest_data)
    #     pattern1 = r'<intent-filter>(.*?)</intent-filter>'
    #     matches = re.findall(pattern1, manifest_data, re.DOTALL)
    #     intent_filter_contents = []
    #     for match in matches:
    #         # intent_filter_contents.append(match.strip())
    #         lines=match.strip().split('\n')
    #         lines=[line.strip() for line in lines]
    #         intent_filter_contents.extend(lines)
    #     intent_filter_contents=[tmp for tmp in intent_filter_contents if not tmp.startswith("<data android:")]
    #     intent_filter_contents=[item.split('"')[1] for item in intent_filter_contents]
    #     return intent_filter_contents

    def get_intent(self):
        intent_filter_contents = []
        try:
            # 获取并解码manifest数据
            manifest_data = self.a.get_android_manifest_axml().get_xml()
            if manifest_data is not None:
                manifest_data = manifest_data.decode('utf-8')
            else:
                print("Manifest data is None.")
                return []
            # 使用正则表达式提取<intent-filter>内容
            pattern1 = r'<intent-filter>(.*?)</intent-filter>'
            matches = re.findall(pattern1, manifest_data, re.DOTALL)
            # 遍历匹配结果，清理并提取intent filter中的动作(action)
            for match in matches:
                lines = [line.strip() for line in match.strip().split('\n') if line.strip()]
                for line in lines:
                    # 直接寻找以android:name开头并提取双引号中的内容，跳过"data"标签
                    if line.startswith('<action android:name='):
                        action = line.split('android:name="')[1].split('"')[0]
                        intent_filter_contents.append(action)
        except Exception as e:
            print(f"捕获到异常: {e}")
            return []
        return intent_filter_contents

    def get_apk_size(self):
        file_size = os.path.getsize(self.apk_path)
        return round(file_size / (1024 * 1024),2)

    # def get_intent(self):
    #     intent_filter_contents = []
    #     path = os.path.join(self.output_dir, 'AndroidManifest.xml')
    #     if not os.path.exists(path):
    #         self.decompile_apk('errorlog')
    #         if not os.path.exists(path):
    #             return None
    #             # raise FileNotFoundError("即使在反编译后，也无法找到AndroidManifest.xml文件。")
    #     with open(path, 'r', encoding='utf-8') as file:
    #         xml_content = file.read()
    #     # 使用正则表达式提取<intent-filter>内容
    #     pattern1 = r'<intent-filter>(.*?)</intent-filter>'
    #     matches = re.findall(pattern1, xml_content, re.DOTALL)
    #
    #     # 遍历匹配结果，清理并提取intent filter中的动作(action)
    #     for match in matches:
    #         lines = [line.strip() for line in match.strip().split('\n') if line.strip()]
    #         for line in lines:
    #             # 直接寻找以android:name开头并提取双引号中的内容，跳过"data"标签
    #             if line.startswith('<action android:name='):
    #                 action = line.split('android:name="')[1].split('"')[0]
    #                 intent_filter_contents.append(action)
    #
    #     return intent_filter_contents
    # def get_activities(self):
    #     activities_filter_contents = []
    #     path = os.path.join(self.output_dir, 'AndroidManifest.xml')
    #
    # def get_apk_size(self):
    #     file_size = os.path.getsize(self.apk_path)
    #     return round(file_size / (1024 * 1024),2)
    #
    # def get_package(self):
    #     path = os.path.join(self.output_dir, 'AndroidManifest.xml')
    #     if not os.path.exists(path):
    #         self.decompile_apk('errorlog')
    #         if not os.path.exists(path):
    #             return None
    #             raise FileNotFoundError("即使在反编译后，也无法找到AndroidManifest.xml文件。")
    #     with open(path, 'r', encoding='utf-8') as file:
    #         xml_content = file.read()
    #     pattern1 = r'package="(.*?)"'
    #     matches = re.findall(pattern1, xml_content, re.DOTALL)
    #     return matches
    #
    # def get_androidversion_name(self):
    #     path = os.path.join(self.output_dir, 'AndroidManifest.xml')
    #     if not os.path.exists(path):
    #         self.decompile_apk('errorlog')
    #         if not os.path.exists(path):
    #             return None
    #             raise FileNotFoundError("即使在反编译后，也无法找到AndroidManifest.xml文件。")
    #     with open(path, 'r', encoding='utf-8') as file:
    #         xml_content = file.read()
    #     pattern1 = r'android:versionName="(.*?)"'
    #     matches = re.findall(pattern1, xml_content, re.DOTALL)
    #     return matches
    #
    # # 数值版本
    # def get_androidversion_code(self):
    #     path = os.path.join(self.output_dir, 'AndroidManifest.xml')
    #     if not os.path.exists(path):
    #         self.decompile_apk('errorlog')
    #         if not os.path.exists(path):
    #             return None
    #             raise FileNotFoundError("即使在反编译后，也无法找到AndroidManifest.xml文件。")
    #     with open(path, 'r', encoding='utf-8') as file:
    #         xml_content = file.read()
    #     pattern1 = r'android:versionCode="(.*?)"'
    #     matches = re.findall(pattern1, xml_content, re.DOTALL)
    #     return matches
    def decompile_apk(self,errorlog):
        # 确保输出目录存在
        if not os.path.exists(self.output_dir):
            os.makedirs(self.output_dir)

        # 构建Apktool命令
        apktool_command = f"apktool d -f {self.apk_path} -o {self.output_dir}"

        try:
            # 使用subprocess.Popen执行命令，指定编码处理输出和错误信息
            process = subprocess.Popen(apktool_command, shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True, encoding='utf-8', errors='replace')

            # 向stdin写入一个回车符来模拟按键，然后刷新缓冲区
            process.stdin.write('\n')
            process.stdin.flush()

            # 等待命令执行完成
            stdout, stderr = process.communicate()

            # 检查返回码，非0表示命令执行出错
            if process.returncode != 0:
                # 当错误发生时，将错误信息中的非法字符替换处理，避免直接打印时的编码错误
                stderr_processed = stderr.encode('utf-8', errors='replace').decode('utf-8')
                raise subprocess.CalledProcessError(process.returncode, apktool_command, output=stdout, stderr=stderr_processed)

            print(f"APK文件已成功解压到{self.output_dir}")

        except subprocess.CalledProcessError as e:
            new_content = self.apk_path + '\n'
            with open(errorlog, 'a', encoding='utf-8') as file:
                file.write(new_content)
            print(f"解压过程中发生错误: {e.stderr}")

    def get_folder_size(self):
        if not os.path.exists(self.output_dir):
            self.decompile_apk('errorlog')
        folder = Path(self.output_dir)
        folder_size=sum(f.stat().st_size for f in folder.glob('**/*') if f.is_file())
        return folder_size/ (1024 * 1024)
    # def get_folder_size(self):
    #     total_size = 0
    #     for dirpath, dirnames, filenames in os.walk(self.output_dir):
    #         for filename in filenames:
    #             file_path = os.path.join(dirpath, filename)
    #             file_path=file_path.replace("\\","/")
    #             p1 = r'\\?'
    #             p2 = '\\'
    #             p3=file_path.replace("/","\\")
    #             file_path=r'{}'.format(p1+p2+p3)
    #             if os.path.exists(file_path):
    #                 return 0
    #             total_size += os.path.getsize()
    #     return round(total_size / (1024 * 1024),2)

    def get_strings(self):
        path = os.path.join(self.output_dir, 'res/values/strings.xml')
        if not os.path.exists(path):
            self.decompile_apk('errorlog')
            if not os.path.exists(path):
                return None
                raise FileNotFoundError("即使在反编译后，也无法找到strings.xml文件。")
        with open(path, 'r', encoding='utf-8') as file:
            xml_content = file.read()

        return xml_content
    # 主题分类


class MyFoldTool:
    def __init__(self,folder):
        self.folder = folder

    # show all information in this folder
    def list_files_and_folders(self):
        for root, dirs, files in os.walk(self.folder):
            level = root.replace(self.folder, '').count(os.sep)
            indent = ' ' * 4 * (level)
            # print('{}{}/'.format(indent, os.path.basename(root)))
            subindent = ' ' * 4 * (level + 1)
            # for f in files:
            #     print('{}{}'.format(subindent, f))
        return root, dirs, files

    # return a list whose elements contain the substring
    def soft_files(self,file_list,substring):
        sub_files = [item for item in file_list if substring in item]
        return sub_files

    # 该函数未单元测试
    def unzip_file(self,files,extract_to_path):
        prefix=''.join([self.folder,'/'])
        prefixed_list_with_join = prefix + ','.join(files)
        print(prefixed_list_with_join.split(','))
        with zipfile.ZipFile(self.folder, 'r') as zip_ref:
            zip_ref.extractall(extract_to_path)

    def traverse_files(self,file_list,extract_to_path):
        for zip in file_list:
            self.unzip_file(zip,extract_to_path)

    # use apktool to decompile the apk in the apk_path and output to output_dir
    def decompile_apk(self,apk_path, output_dir):
        try:
            # 构建Apktool的命令行指令
            cmd = ['apktool', 'd', apk_path, '-o', output_dir]

            # 使用subprocess.run执行命令，添加capture_output=True来捕获输出信息
            result = subprocess.run(cmd, capture_output=True, text=True)

            # 检查命令执行状态
            if result.returncode == 0:
                print("APK解压成功")
                # 可选：打印Apktool的输出信息
                # print(result.stdout)
            else:
                print("APK解压失败")
                print("错误信息:", result.stderr)
        except FileNotFoundError:
            print("Apktool未找到，请确保Apktool已安装并在PATH中")
        except Exception as e:
            print("解压过程中发生错误:", e)

    def traverse_folder(self):
        """
        遍历文件夹及其子文件夹和文件,并将信息存储在字典中。

        参数:
        folder_path (str) - 要遍历的文件夹路径

        返回:
        dict - 包含文件夹及其文件信息的字典
        """
        file_info = {}

        for root, dirs, files in os.walk(self.folder):
            # 将当前目录存储在字典中
            file_info[root] = {
                "subdirs": dirs,
                "files": files
            }

        return file_info

# apkDecompiler=ApkDecompiler("SoftwareFolder/2c.apk","SoftwareFolder2/2c.apk")
# tmp=apkDecompiler.get_strings()
# print(tmp)

def run_decompile_apk(folder_path,output):
    my_foldertool = MyFoldTool(folder_path)
    root, dirs, files=my_foldertool.list_files_and_folders()
    apk_path=["/".join([folder_path,tmp]) for tmp in files]
    output_dir=["/".join([output,tmp]) for tmp in files]
    if len(apk_path)==len(output_dir):
        for i in range(len(apk_path)):
            decompile_apk2(apk_path[i],output_dir[i])
#
# start_time = time.time()
# run_decompile_apk("dataset/sex","E:/软件杯/sex")
# run_decompile_apk("dataset/scam","E:/软件杯/scam")
# run_decompile_apk("dataset/black","E:/软件杯/black")
# run_decompile_apk("dataset/gamble","E:/软件杯/gamble")
# run_decompile_apk("dataset/batch1","E:/软件杯/batch")
# run_decompile_apk("dataset/batch2","E:/软件杯batch")
# run_decompile_apk("dataset/batch3","E:/软件杯/batch")
# run_decompile_apk("dataset/batch4","E:/软件杯/batch")
# end_time = time.time()
# execution_time = end_time - start_time
# print(f"代码执行时间: {execution_time}秒")